package com.yc.cloud.common.pay.service.impl;

import cn.hutool.json.JSONUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.yc.cloud.common.pay.config.WxPayConfig;
import com.yc.cloud.common.pay.dto.PayNotifyDto;
import com.yc.cloud.common.pay.dto.QueryOrderByOutTradeNoDto;
import com.yc.cloud.common.pay.dto.request.WxCreateOrderParam;
import com.yc.cloud.common.pay.service.WxPayService;
import com.yc.cloud.common.pay.utils.HttpServletUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    private JsapiServiceExtension jsapiServiceExtension;
    @Autowired(required = false)
    private RSAAutoCertificateConfig rsaAutoCertificateConfig;

//    public WxPayServiceImpl(RSAAutoCertificateConfig rsaAutoCertificateConfig) {
//        this.rsaAutoCertificateConfig = rsaAutoCertificateConfig;
//        log.info("WxPayServiceImpl....");
//    }


    @PostConstruct
    public void init() {
        if (rsaAutoCertificateConfig == null) {
            return;
        }
        jsapiServiceExtension = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).signType("RSA").build(); // 不填默认为RSA
    }


    @Resource
    private WxPayConfig wxPayConfig;

    @Override
    public PrepayWithRequestPaymentResponse createOrder(WxCreateOrderParam param) {
        PrepayWithRequestPaymentResponse response = new PrepayWithRequestPaymentResponse();
        try {
            PrepayRequest request = new PrepayRequest();
            request.setAppid(wxPayConfig.getAppId());
            request.setMchid(wxPayConfig.getMerchantId());
            request.setDescription(param.getDescription());
            request.setOutTradeNo(param.getOrderNo());
            request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());
            Amount amount = new Amount();
            amount.setTotal(param.getAmount());
            request.setAmount(amount);
            Payer payer = new Payer();
            payer.setOpenid(param.getOpenId());
            request.setPayer(payer);
            log.info("请求预支付下单，请求参数：{}", JSONUtil.toJsonStr(request));
            // 调用预下单接口
            response = jsapiServiceExtension.prepayWithRequestPayment(request);
            log.info("订单【{}】发起预支付成功，返回信息：{}", param.getOrderNo(), response);
            return response;
        } catch (HttpException e) { // 发送HTTP请求失败
            log.error("微信下单发送HTTP请求失败，错误信息：{}", e.getHttpRequest());
            // return R.error().message("下单失败");
        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300，例如500
            log.error("微信下单服务状态错误，错误信息：{}", e.getErrorMessage());
            // return R.error().message("下单失败");
        } catch (MalformedMessageException e) { // 服务返回成功，返回体类型不合法，或者解析返回体失败
            log.error("服务返回成功，返回体类型不合法，或者解析返回体失败，错误信息：{}", e.getMessage());
        }
        return null;
    }

    @Override
    public PayNotifyDto payNotifyParser(HttpServletRequest request) {
        log.info("------收到支付通知------");
        // 请求头Wechatpay-Signature
        String signature = request.getHeader("Wechatpay-Signature");
        // 请求头Wechatpay-nonce
        String nonce = request.getHeader("Wechatpay-Nonce");
        // 请求头Wechatpay-Timestamp
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        // 微信支付证书序列号
        String serial = request.getHeader("Wechatpay-Serial");
        // 签名方式
        String signType = request.getHeader("Wechatpay-Signature-Type");
        // 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder().serialNumber(serial).nonce(nonce).signature(signature).timestamp(timestamp).signType(signType).body(HttpServletUtils.getRequestBody(request)).build();
        // 初始化 NotificationParser
        NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);
        // 以支付通知回调为例，验签、解密并转换成 Transaction
        //log.info("验签参数：{}", requestParam);
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        log.info("验签成功！-支付回调结果：{}", transaction.toString());
        if (Transaction.TradeStateEnum.SUCCESS == transaction.getTradeState()) {
            //log.info("内部订单号【{}】,微信支付订单号【{}】支付成功", transaction.getOutTradeNo(), transaction.getTransactionId());
            //todo 是否还需要校验下商户号、appid等信息是否一致
            //if (wxPayConfig.getAppId().equals(transaction.getAppid()) && wxPayConfig.getMerchantId().equals(transaction.getMchid())) {
            return new PayNotifyDto(transaction.getOutTradeNo(), transaction.getTransactionId(), transaction.getAmount().getTotal());
            //}
        }
        return null;
    }

    @Override
    public QueryOrderByOutTradeNoDto queryOrderByOutTradeNo(String orderNo) {
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(wxPayConfig.getMerchantId());
        queryRequest.setOutTradeNo(orderNo);
        Transaction result = jsapiServiceExtension.queryOrderByOutTradeNo(queryRequest);
        boolean paySuccess = false;
        if (Transaction.TradeStateEnum.SUCCESS == result.getTradeState()) {
            log.info("内部订单号【{}】,微信支付订单号【{}】支付成功", result.getOutTradeNo(), result.getTransactionId());
            paySuccess = true;
        }
        return new QueryOrderByOutTradeNoDto(result.getOutTradeNo(), result.getTransactionId(), paySuccess);
    }
}
